use crate::fs::operation::OpenMode;

use super::{check_and_clone_cstr, data::Stat, SysError, SysResult, Syscall};

impl Syscall<'_> {
    pub fn sys_open(&mut self, path: *const u8, mode: usize) -> SysResult {
        let path = check_and_clone_cstr(path)?;

        if let Some(ret) = crate::fs::operation::open(path.clone(), OpenMode::from(mode)) {
            return Ok(ret);
        }
        Err(SysError::EBADF)
    }

    pub fn sys_close(&mut self, fd: usize) -> SysResult {
        crate::fs::operation::close(fd);
        Ok(0)
    }

    pub fn sys_read(&mut self, fd: usize, buf: usize, buf_size: usize) -> SysResult {
        let buffer = unsafe { core::slice::from_raw_parts_mut(buf as _, buf_size) };
        Ok(crate::fs::operation::read(fd, buffer))
    }

    pub fn sys_write(&mut self, fd: usize, buf: usize, buf_size: usize) -> SysResult {
        let buffer = unsafe { core::slice::from_raw_parts(buf as _, buf_size) };
        Ok(crate::fs::operation::write(fd, buffer))
    }

    pub fn sys_fsize(&mut self, fd: usize) -> SysResult {
        crate::fs::operation::fsize(fd).ok_or(SysError::EBADF)
    }

    pub fn sys_fstat(&mut self, fd: usize, ret_buf: *mut Stat) -> SysResult {
        let ret = &mut unsafe { *ret_buf };
        ret.st_size = crate::fs::operation::fsize(fd).ok_or(SysError::EBADF)? as u64;
        ret.st_blksize = 512;
        ret.st_blocks = (ret.st_size + ret.st_blksize as u64 - 1) / ret.st_blksize as u64;

        Ok(0)
    }
}
